package com.carbeauty.image.indexing;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.imageio.ImageIO;

import net.semanticmetadata.lire.DocumentBuilder;

import org.apache.lucene.document.Document;

import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.MetadataException;
import com.drew.metadata.exif.ExifDirectory;
import com.drew.metadata.exif.ExifReader;

public class ImageIndexer  implements Runnable {
	 Vector<String> imageFiles;
	    private int NUMBER_OF_SYNC_THREADS = 4;
	    Hashtable<String, Boolean> indexThreads = new Hashtable<String, Boolean>(3);
	    DocumentBuilder builder;
	    Vector<Document> finished = new Vector<Document>();
	    private boolean started = false;
	    private final ExecutorService pool;
	    private int countImagesOut = 0;
	    private int countImagesProcesses = 0;
	    public ImageIndexer(List<String> imageFiles, DocumentBuilder b) {
	        this.imageFiles = new Vector<String>();
	        assert (imageFiles != null);
	        this.imageFiles.addAll(imageFiles);
	        builder = b;
	        pool = Executors.newFixedThreadPool(NUMBER_OF_SYNC_THREADS);
	    }
	    public void run() {
	        for (int i = 1; i < NUMBER_OF_SYNC_THREADS; i++) {
	            PhotoIndexer runnable = new PhotoIndexer(this);
	            pool.submit(runnable);
	        }
	        started = true;
	    }

	    public void addDoc(Document doc, String photofile) {
	        if (doc != null) finished.add(doc);
	        Thread.yield();
	    }

	    public Document getNext() {
	        if (imageFiles.size() < 1) {
	            boolean fb = true;
	            for (String t : indexThreads.keySet()) {
	                fb = fb && indexThreads.get(t);
	            }
	            if (started && fb) {
	                return null;
	            }
	        }
	        while (finished.size() < 1) {
	            try {
	                Thread.sleep(10);
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	        }
	        return finished.remove(0);
	    }

	    private String getNextImage() {
	        if (imageFiles.size() > 0) {
	            countImagesOut++;
	            return imageFiles.remove(0);
	        } else {
	           // System.out.println("countImagesOut = " + countImagesOut);
	            return null;
	        }
	    }

	    class PhotoIndexer implements Runnable {
	        String photo;
	        ImageIndexer parent;
	        private boolean hasFinished = false;
	        PhotoIndexer(ImageIndexer parent) {
	            this.parent = parent;
	        }
	        public void run() {
	            parent.indexThreads.put(Thread.currentThread().getName(), false);
	            while ((photo = parent.getNextImage()) != null) {
	                try {
	                	parent.createImageIndex(  photo);
	                } catch (Exception e) {
	                    e.printStackTrace();
	                    parent.addDoc(null, photo);
	                }
	            }
	            parent.indexThreads.put(Thread.currentThread().getName(), true);
	        }
	    }
	    
	    public void  createImageIndex(String photo) throws IOException{
	    	  BufferedImage image = readFile(photo);
	    	  Document doc =  builder.createDocument(image, photo);
              addDoc(doc, photo);
	    }
	    
	    public Document createDocument(String photo)throws IOException{
	    	  BufferedImage image = readFile(photo);
	    	  return builder.createDocument(image, photo);
	    }
	    
	    public   static BufferedImage  readFile(String path) throws IOException {
	        BufferedImage image = null;
	        FileInputStream jpegFile = new FileInputStream(path);
	        Metadata metadata = new Metadata();
	        try {
	        	  ExifReader exif = new ExifReader(jpegFile);  
	        	exif.extract(metadata);
	            Iterator itr = metadata.getDirectoryIterator();   
//	            while (itr.hasNext()) {
//	            	 Directory directory = (Directory) itr.next();
//	            System.out.println("EXIF版本：" + directory.getString(ExifDirectory.TAG_EXIF_VERSION));       
//	            System.out.println("相机品牌：" + directory.getString(ExifDirectory.TAG_MAKE));       
//	            System.out.println("相机型号：" + directory.getString(ExifDirectory.TAG_MODEL));       
//	            System.out.println("光 圈 值：" + directory.getString(ExifDirectory.TAG_FNUMBER));       
//	            System.out.println("快    门：" + directory.getString(ExifDirectory.TAG_EXPOSURE_TIME));      
//	            System.out.println("感 光 度：" + directory.getString(ExifDirectory.TAG_ISO_EQUIVALENT));   
//	            System.out.println("软    件：" + directory.getString(ExifDirectory.TAG_SOFTWARE));     
//	            System.out.println("原始拍摄时间：" + directory.getString(ExifDirectory.TAG_DATETIME_ORIGINAL));    
//	            System.out.println("数字化时间：" + directory.getString(ExifDirectory.TAG_DATETIME_DIGITIZED));   
//	            System.out.println("方    向：" + directory.getString(ExifDirectory.TAG_ORIENTATION));    
//	            System.out.println("图片宽度：" + directory.getString(ExifDirectory.TAG_EXIF_IMAGE_WIDTH));   
//	            System.out.println("图片高度：" + directory.getString(ExifDirectory.TAG_EXIF_IMAGE_HEIGHT));   
//	            System.out.println("水平分辨率：" + directory.getString(ExifDirectory.TAG_X_RESOLUTION));    
//	            System.out.println("垂直分辨率：" + directory.getString(ExifDirectory.TAG_Y_RESOLUTION));    
//	            System.out.println("垂直分辨率：" + directory.getString(ExifDirectory.TAG_EXPOSURE_BIAS));
//	            }
	            byte[] thumb = ((ExifDirectory) metadata.getDirectory(ExifDirectory.class)).getThumbnailData();
	            if (thumb != null) image = ImageIO.read(new ByteArrayInputStream(thumb));
	        } catch (JpegProcessingException e) {
	            System.err.println("Could not extract thumbnail");
	            e.printStackTrace();
	        } catch (MetadataException e) {
	            System.err.println("Could not extract thumbnail");
	            e.printStackTrace();
	        } catch (Exception e) {
	            System.err.println("Could not extract thumbnail");
	            e.printStackTrace();
	        }
	        // Fallback:
	        if (image == null) image = ImageIO.read(new FileInputStream(path));
	        return image;
	    }	    

}
